// 2013-8-1下午12:49:05  net.betou.trade.main.manager.impl.UserMngImpl.java

package net.betou.trade.main.manager.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import net.betou.common.hibernate3.Updater;
import net.betou.common.page.Pagination;
import net.betou.common.security.encoder.PwdEncoder;
import net.betou.common.security.encoder.SaltGenerator;
import net.betou.common.security.exception.BadCredentialsException;
import net.betou.common.security.exception.UsernameNotFoundException;
import net.betou.common.util.DataConvertUtils;
import net.betou.common.util.DateUtils;
import net.betou.core.entity.ConfigLogin;
import net.betou.pojo.Report;
import net.betou.trade.entity.main.AgentAndAdmins;
import net.betou.trade.entity.main.User;
import net.betou.trade.entity.main.UserExt;
import net.betou.trade.entity.main.UserGroup;
import net.betou.trade.main.dao.UserDao;
import net.betou.trade.main.dao.agencyorproxy.AdminDao;
import net.betou.trade.main.manager.UserExtMng;
import net.betou.trade.main.manager.UserGroupMng;
import net.betou.trade.main.manager.UserMng;
import net.betou.trade.role.setting.CommonFinderConfig;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 
 * @author 叶装装
 */
@Service
@Transactional
public class UserMngImpl implements UserMng{
	
	@Transactional( readOnly = true )
	public List< Report > findMonthReport( String month ){
		return dao.findMonthReport( month );
	}
	
	@Transactional( readOnly = true )
	public List< Report > findDayReport( String day ){
		return dao.findDayReport( day );
	}
	
	@Transactional( readOnly = true )
	public List< String > findDayReportChoice( String year ){
		return dao.findReportChoice( year, "%Y-%m-%d", "day" );
	}
	@Transactional( readOnly = true )
	public List< String > findMonthReportChoice( String year ){
		return dao.findReportChoice( year, "%Y-%m", "month" );
	}
	@Transactional( readOnly = true )
	public List< String > findYearReportChoice( ){
		return dao.findReportChoice( null, null, null );
	}
	
	
	
	@Transactional( readOnly = true )
	public boolean demoAccountExit( String demoAccount ){
		return dao.countDemoAccount( demoAccount ) <= 0;
	}
	@Transactional( readOnly = true )
	public boolean firmAccountExit( String firmAccount ){
		return dao.countFirmAccount( firmAccount ) <= 0;
	}
	
	public User deleteById( Integer id ) {
		return dao.deleteById( id );
	}

	public User [ ] deleteByIds( Integer [ ] ids ) {
		User [ ] beans = new User [ ids.length ];
		for ( int i = 0; i < ids.length; i++ ){
			beans[ i ] = dao.deleteById( ids[ i ] );
		}
		return beans;
	}
	
	@Transactional( readOnly = true )
	public boolean emailNotExist( String email ) {
		return dao.countByEmail( email ) <= 0;
	}

	@Transactional( readOnly = true )
	public User findById( Integer id ) {
		return dao.findById( id );
	}

	@Transactional( readOnly = true )
	public User findByUsername( String username ) {
		return dao.findByUsername( username );
	}

	@Transactional( readOnly = true )
	public Pagination getPage( AgentAndAdmins admin, String searchProperty, String searchValue, String orderProperty, String orderDirection, int pageNo, int pageSize, String filterStatus ) {
		
		if( admin.getSystem( ) ){
			return dao.getPage( null, searchProperty, searchValue, orderProperty, orderDirection, pageNo, pageSize, filterStatus );
		}
		
		CommonFinderConfig config = new CommonFinderConfig( admin, ConfigLogin.CONFIG_USER );
		
		if( config.isSelf( ) ){
			return dao.getPage( admin.getId( ), searchProperty, searchValue, orderProperty, orderDirection, pageNo, pageSize, filterStatus );
		}
		
		return dao.getPageByCriteria( searchProperty, searchValue, orderProperty, orderDirection, pageNo, pageSize, config.getDeepSQL( ) );
	}
	
	/**
	 * 获取非直属的
	 */
	@Transactional( readOnly = true )
	public List< String > getMobileList( AgentAndAdmins admin, String groups ){
		
		if( admin == null ){
			return null;
		}
		
		if( StringUtils.isBlank( groups ) ){
			return null;
		}
		
		String [ ] groupsArr = StringUtils.split( groups, "," );
		
		if( groupsArr == null || groupsArr.length == 0 ){
			return null;
		}
		
		List<  String > mobileList = new ArrayList< String >( );
		
		int pageSize = 1;
		
		Pagination p = getPage( admin, null, null, null, null, 1, pageSize, null );
		
		loopPage( p, groupsArr, mobileList );
		
		for( int i = 2; i <= p.getTotalPage( ); i++ ){
			p = getPage( admin, null, null, null, null, i, pageSize, null );
			loopPage( p, groupsArr, mobileList );
		}
		
		if( mobileList.isEmpty( ) ){
			return null;
		}
		
		return mobileList;
		
	}
	
	@SuppressWarnings( "unchecked" )
	private List< String > loopPage( Pagination p, String [ ] groupArr, List< String > mobileList ){
		
		List< User > userList = ( List< User > ) p.getList( );
		
		for( User user : userList ){
			
			for( int i = 0; i < groupArr.length; i++ ){
				if( user.getGroup( ).getId( ) ==  DataConvertUtils.getInt( groupArr[ i ] ) ){
					mobileList.add( user.getMobile( ) );
				}
			}
			
		}
		
		return mobileList;
		
	}
	
	/**
	 * 获取直属的
	 */
	@Transactional( readOnly = true )
	public List< String > getMobileList( Integer adminId, String groups ) {
		
		if( adminId == null || adminId == 0 ){
			return null;
		}
		
		if( StringUtils.isBlank( groups ) ){
			return null;
		}
		
		String [ ] groupsArr = StringUtils.split( groups, "," );
		
		if( groupsArr == null || groupsArr.length == 0 ){
			return null;
		}
		
		List< String > mobileList = dao.getMobileList( adminId, groupsArr );
		
		if( mobileList.isEmpty( ) ){
			return null;
		}
		
		return mobileList;
	}

	public User login( String username, String password, String ip ) throws UsernameNotFoundException, BadCredentialsException {
		// 要根据手机，用户名或者邮箱
		
		User user = dao.findByQuery( username );
		
		if( user == null ){
			throw new UsernameNotFoundException( "username not found: " + username ); 
		}
		
		if( !pwdEncoder.isPasswordValid( user.getPassword( ), password, user.getSalt( ) ) ){
			throw new BadCredentialsException( "password invalid" );
		}
		
		if(! user.getDisabled( ) && !user.getExpire( ) ){
			updateLoginInfo( user, ip );
		}
		return user;
	}
	
	private void updateLoginInfo( User user, String ip ){
		if( user != null ){
			user.setLoginCount( user.getLoginCount( ) + 1 );
			user.setLoginIp( ip );
			user.setLoginDate( new Date( ) );
		}
	}

	@Transactional( readOnly = true )
	public boolean mobileNotExist( String mobile ) {
		return dao.countByMobile( mobile ) <= 0;
	}

	public void updateLoginInfo( Integer userId, String ip ) {
		User user = findById( userId );
		if( user != null ){
			user.setLoginCount( user.getLoginCount( ) + 1 );
			user.setLoginIp( ip );
			user.setLoginDate( new Date( ) );
		}
	}

	@Transactional( readOnly = true )
	public boolean userNameNotExist( String username ) {
		return dao.countByUsername( username ) <= 0;
	}
	
	
	
	public User update( Byte status, String expireDate, Integer groupId, String email, String password, String mobile, Boolean disabled, String demoAccount, String demoAccountPwd,
									  String firmAccount, String firmAccountPwd,
									  User user, UserExt ext ){
		
		
		user.setEmail( StringUtils.isNotBlank( email ) ? email : null );
		user.setMobile( StringUtils.isNotBlank( mobile ) ? mobile : null );
		
		String loginSalt = user.getSalt( ); // 获取原来的salt
		
		// 更新密码的时候重置salt
		if( StringUtils.isNotBlank( password ) ){
			user.setPassword( pwdEncoder.encodePassword( password, loginSalt ) );
		}
		
		if( StringUtils.isNotBlank( demoAccount )){
			user.setDemoAccount( demoAccount );
		}else{
			user.setDemoAccount( null );
		}
		
		if( StringUtils.isNotBlank( firmAccount )){
			user.setFirmAccount( firmAccount );
		}else{
			user.setFirmAccount( null );
		}
		
		// 设置模拟账号
		if( StringUtils.isNotBlank(  demoAccount  ) && StringUtils.isNotBlank( demoAccountPwd )){
			user.setDemoAccountPwd( pwdEncoder.encodePassword( demoAccountPwd, loginSalt ) );
		}
		// 设置实盘账号
		if( StringUtils.isNotBlank( firmAccount ) && StringUtils.isNotBlank( firmAccountPwd )){
			user.setFirmAccount( firmAccountPwd );
			user.setFirmAccountPwd( pwdEncoder.encodePassword( firmAccountPwd, loginSalt ) );
		}
		
		UserGroup group;
		if( groupId != null ){
			group = groupMng.findById( groupId );
		}else{
			group = groupMng.findByDefault( );
		}
		
		if( disabled == null ){
			user.setDisabled( true );
		}else{
			user.setDisabled( false );
		}
		
		user.setStatus( status );
		user.setExpireDate( DateUtils.format( expireDate ) );
		
		user.setGroup( group );
		
		Updater< User > updater = new Updater< User >( user );
		updater.exclude( "username" );
		updater.exclude( "regDate" );
		updater.exclude( "regIp" );
		updater.exclude( "loginDate" );
		updater.exclude( "loginIp" );
		updater.exclude( "loginCount" );
		updater.exclude( "admin" );
		
		user = dao.updateByUpdater( updater ); // 更新主表
		mng.update( ext, user ); // 更新附表
		
		return user;
	}
	
	
	@Transactional( readOnly = true )
	public User findMyUser( Integer userid, Integer adminId, Boolean system ){
		if( system ){
			return dao.findById( userid );
		}
		return dao.findMyUser( userid, adminId );
	}
	
	public User save( AgentAndAdmins admin, Integer groupId, String ip, User bean, UserExt ext ){
		
		bean.setRegIp( ip );
		
		String loginSalt = salt.randomSalt( );

		bean.setSalt( loginSalt );
		bean.setPassword( pwdEncoder.encodePassword( bean.getPassword( ), loginSalt ) ); // 设置登录密码的
		
		String demoAccountPwd = bean.getDemoAccountPwd( );
		String firmAccountPwd = bean.getFirmAccountPwd( );
		
		// 设置模拟账号
		if( StringUtils.isNotBlank(  bean.getDemoAccount( )  ) && StringUtils.isNotBlank( demoAccountPwd )){
			bean.setDemoAccountPwd( pwdEncoder.encodePassword( demoAccountPwd, loginSalt ) );
		}
		// 设置实盘账号
		if( StringUtils.isNotBlank( bean.getFirmAccount( ) ) && StringUtils.isNotBlank( firmAccountPwd )){
			bean.setFirmAccountPwd( pwdEncoder.encodePassword( firmAccountPwd, loginSalt ) );
		}
		
		bean.initToSave( );
		UserGroup group;
		
		if( groupId == null ){
			group = groupMng.findByDefault( );
		}else{
			group = groupMng.findById( groupId );
		}
		
		bean.setGroup( group );
		bean.setAdmin( admin );
		
		dao.save( bean );
		
		mng.save( ext, bean );
		
		return bean;
		
		
	}
	
	@Transactional( readOnly = true )
	public AgentAndAdmins getProxyOrAgency( User user ){
		AgentAndAdmins admin = user.getAdmin( );
		
		if( admin.getAgency( ) ){
			return admin;
			
		}else if( admin.getProxy( ) ){
			return admin;
		}else{
			String [ ] tops = StringUtils.split( admin.getTopIntermedia( ), "," );
			
			for( int i = tops.length - 1; i >= 0; i-- ){
				Integer id = DataConvertUtils.getInt( tops[ i ] );
				AgentAndAdmins bean = adminDao.findById( id );
				
				if( bean == null ){
					continue;
				}
				
				if( bean.getProxy( ) || bean.getAgency( ) ){
					return bean;
				}
			}
		}
		
		return admin;
		
	}
	
	@Transactional( readOnly = true )
	public List< Integer > getSearchId( User user ){
		AgentAndAdmins admin = user.getAdmin( );
		
		List< Integer > idList = new ArrayList< Integer >( );
		// 直接是机构
		if( admin.getAgency( ) ){
			idList.add( admin.getId( ) );
		// 是代理商
		}else if( admin.getProxy( ) ){
			idList.add( admin.getId( ) ); // 存放代理商的ID, 就是等于存放了自己的ID
			
			String [ ] tops = StringUtils.split( admin.getTopIntermedia( ), "," );
			
			for( int i = tops.length - 1; i >= 0; i-- ){
				Integer id = DataConvertUtils.getInt( tops[ i ] );
				AgentAndAdmins bean = adminDao.findById( id );
				
				if( bean == null ){
					continue;
				}
				// 只要是机构或者代理商，不管是多少层的机构，都添加进去
				if( bean.getAgency( ) || bean.getProxy( ) ){
					idList.add( bean.getId( ) );
				}
			}
		}else{
			String [ ] tops = StringUtils.split( admin.getTopIntermedia( ), "," );
			
			for( int i = tops.length - 1; i >= 0; i-- ){
				Integer id = DataConvertUtils.getInt( tops[ i ] );
				AgentAndAdmins bean = adminDao.findById( id );
				
				if( bean == null ){
					continue;
				}
				
				if( bean.getProxy( ) || bean.getAgency( ) ){
					idList.add( bean.getId( ) );
				}
			}
			
			idList.add( admin.getId( ) ); // 还要加入自己的ID
		}
		
		
		return idList;
	}
	
	@Autowired
	private UserDao dao;
	
	@Autowired
	private UserExtMng mng;
	
	@Autowired
	private UserGroupMng groupMng;
	
	@Autowired
	private PwdEncoder pwdEncoder;
	
	@Autowired
	private SaltGenerator salt;
	
	@Autowired
	private AdminDao adminDao;
}
